home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 April: Mac OS SDK / Dev.CD Apr 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / Plug-in - Attr / NameAttrTest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  24.7 KB  |  954 lines  |  [TEXT/CWIE]

  1. /* this is box, modified to be a test for the name plug-in attribute */
  2.  
  3. // NameAttrTest.c - QuickDraw 3d routines
  4. //
  5. // This is box, the QuickDraw 3D starter program.  Written for the
  6. // Getting started with QuickDraw 3D Develop article.  This app does not have 
  7. // graceful error handling - it's purpose is to illustrate a very basic QuickDraw 
  8. // 3D program.
  9. //
  10. // Nick Thompson, Robert Dierkes - April 24, 1997
  11. // 
  12. // ©1994-97 Apple computer Inc., All Rights Reserved
  13. //
  14.  
  15. // system headers
  16. #include <Devices.h>
  17. #include <Dialogs.h>
  18. #include <DiskInit.h>
  19. #include <Fonts.h>
  20. #include <Menus.h>
  21. #include <PictUtils.h>
  22. #include <QDOffScreen.h>
  23. #include <QuickDraw.h>
  24. #include <SegLoad.h>
  25. #include <StandardFile.h>
  26. #include <TextEdit.h>
  27.  
  28. #include <strings.h>
  29. #include <string.h>
  30. // for QuickDraw 3D
  31. #include "QD3D.h"
  32. #include "QD3DAcceleration.h"
  33. #include "QD3DCamera.h"
  34. #include "QD3DDrawContext.h"
  35. #include "QD3DGeometry.h"
  36. #include "QD3DGroup.h"
  37. #include "QD3DLight.h"
  38. #include "QD3DMath.h"
  39. #include "QD3DPick.h"
  40. #include "QD3DRenderer.h"
  41. #include "QD3DSet.h"
  42. #include "QD3DShader.h"
  43. #include "QD3DTransform.h"
  44.  
  45. #include "NameAttribute.h"
  46. //-------------------------------------------------------------------------------------------
  47.  
  48. struct _documentRecord {
  49.     TQ3ViewObject    fView ;                    // the view for the scene
  50.     TQ3GroupObject    fModel ;                // object in the scene being modelled
  51.     TQ3StyleObject    fInterpolation ;        // interpolation style used when rendering
  52.     TQ3StyleObject    fBackFacing ;            // whether to draw shapes that face away from the camera
  53.     TQ3StyleObject    fFillStyle ;            // whether drawn as solid filled object or decomposed to components
  54.     TQ3Matrix4x4        fRotation;            // the transform for the model
  55. };
  56.  
  57. typedef struct _documentRecord DocumentRec, *DocumentPtr, **DocumentHdl ;
  58.  
  59.  
  60. //-------------------------------------------------------------------------------------------
  61. // function prototypes
  62.  
  63. void InitDocumentData( 
  64.     DocumentPtr theDocument ) ;
  65.  
  66. void DisposeDocumentData( 
  67.     DocumentPtr theDocument ) ;
  68.  
  69. void     SubmitDocumentData( 
  70.     DocumentPtr theDocument ) ;
  71.  
  72. TQ3Status DocumentDraw3DData( 
  73.     DocumentPtr theDocument ) ;
  74.  
  75. short HiWrd(
  76.     long aLong) ;
  77.  
  78. short LoWrd(
  79.     long aLong ) ;
  80.  
  81. void InitToolbox(
  82.     void ) ;
  83.  
  84. void PickAndProcess( 
  85.     WindowPtr     window,
  86.     DocumentPtr    theDocument, 
  87.     Point         mouseLoc ) ;
  88.  
  89. void ChangeObjectName(
  90.     TQ3GeometryObject    objectPicked,
  91.     TQ3AttributeSet        attribSet) ;
  92.  
  93. void MainEventLoop(
  94.     void ) ;
  95.  
  96. void HandleKeyPress(
  97.     EventRecord *event ) ;
  98.  
  99. TQ3ViewObject MyNewView(
  100.     WindowPtr theWindow ) ;
  101.  
  102. TQ3DrawContextObject MyNewDrawContext(
  103.     WindowPtr theWindow ) ;
  104.  
  105. TQ3CameraObject MyNewCamera(
  106.     WindowPtr theWindow) ;
  107.  
  108. TQ3GroupObject MyNewLights(
  109.     void ) ;
  110.  
  111. void MyColorBoxFaces( 
  112.     TQ3BoxData *myBoxData ) ;
  113.  
  114. TQ3GroupPosition MyAddTransformedObjectToGroup( 
  115.     TQ3GroupObject theGroup, 
  116.     TQ3Object theObject, 
  117.     TQ3Vector3D *translation ) ;
  118.  
  119. TQ3GroupObject MyNewModel(
  120.     void ) ;
  121.  
  122.  
  123. //-------------------------------------------------------------------------------------------
  124. //
  125.  
  126. Boolean         gQuitFlag         = false ;
  127. WindowPtr        gMainWindow        = nil ;
  128. DocumentRec        gDocument ;
  129.  
  130. //-------------------------------------------------------------------------------------------
  131. // main()
  132. // entry point for the application, initialize the toolbox, initialize QuickDraw 3D
  133. // and enter the main event loop.  On exit from the main event loop, we want to call
  134. // the QuickDraw 3D exit function to clean up QuickDraw 3d.
  135.  
  136. void main(void)
  137. {
  138.     TQ3Status    myStatus;
  139.     Rect        rBounds = { 50, 50, 450, 450 } ;
  140.     Str255        title = "\pName Attributes on Geometries" ;
  141.  
  142.     InitToolbox() ;
  143.  
  144.     //    Initialize QuickDraw 3D, open a connection to the QuickDraw 3D library
  145.     myStatus = Q3Initialize();
  146.  
  147.     if ( myStatus == kQ3Failure )
  148.     {
  149.         DebugStr("\pQ3Initialize returned failure.  Use QD3D debug version to find out why.");    
  150.         ExitToShell() ;
  151.     }    
  152.  
  153.     // set up our globals
  154.     gQuitFlag = false ;
  155.     gMainWindow = NewCWindow(nil,&rBounds,title,true,noGrowDocProc,(WindowPtr)-1,true,0) ;
  156.  
  157.     InitDocumentData( &gDocument ) ;
  158.     
  159.     MainEventLoop();
  160.     
  161.     DisposeDocumentData( &gDocument ) ;
  162.     
  163.     //    Close our connection to the QuickDraw 3D library
  164.     myStatus = Q3Exit();
  165.     
  166.     if ( myStatus == kQ3Failure )
  167.         DebugStr("\pQ3Exit returned failure.  Use debug version to find out why");
  168.     
  169.     ExitToShell() ;
  170. }
  171.  
  172. //-------------------------------------------------------------------------------------------
  173. //
  174.  
  175. void InitDocumentData( DocumentPtr theDocument ) 
  176. {
  177.     // sets up the 3d data for the scene
  178.     // Create view for QuickDraw 3D.
  179.     theDocument->fView = MyNewView( (WindowPtr)gMainWindow ) ;
  180.  
  181.     // the main display group:
  182.     theDocument->fModel = MyNewModel() ;
  183.  
  184.     // the drawing styles:
  185.     theDocument->fInterpolation = Q3InterpolationStyle_New(kQ3InterpolationStyleNone) ;
  186.     theDocument->fBackFacing = Q3BackfacingStyle_New(kQ3BackfacingStyleBoth ) ;
  187.     theDocument->fFillStyle = Q3FillStyle_New(kQ3FillStyleFilled ) ;
  188.  
  189.     // set the rotation matrix the identity matrix
  190.     Q3Matrix4x4_SetIdentity(&theDocument->fRotation);
  191. }
  192.  
  193. //-----------------------------------------------------------------------------
  194. // 
  195.  
  196. void DisposeDocumentData( DocumentPtr theDocument)
  197. {
  198.     Q3Object_Dispose(theDocument->fView) ;                // the view for the scene
  199.     Q3Object_Dispose(theDocument->fModel) ;                // object in the scene being modelled
  200.     Q3Object_Dispose(theDocument->fInterpolation) ;        // interpolation style used when rendering
  201.     Q3Object_Dispose(theDocument->fBackFacing) ;        // whether to draw shapes that face away from the camera
  202.     Q3Object_Dispose(theDocument->fFillStyle) ;            // whether drawn as solid filled object or decomposed to components
  203.  
  204. }
  205.  
  206. //-----------------------------------------------------------------------------
  207. // 
  208. void     SubmitDocumentData( 
  209.     DocumentPtr theDocument ) 
  210. {
  211.     Q3Style_Submit( theDocument->fInterpolation, theDocument->fView );
  212.     Q3Style_Submit( theDocument->fBackFacing, theDocument->fView );
  213.     Q3Style_Submit( theDocument->fFillStyle, theDocument->fView );
  214.     Q3MatrixTransform_Submit( &theDocument->fRotation, theDocument->fView );
  215.     Q3DisplayGroup_Submit( theDocument->fModel, theDocument->fView );
  216. }
  217.  
  218. //-----------------------------------------------------------------------------
  219. // 
  220. TQ3Status DocumentDraw3DData( DocumentPtr theDocument )
  221. {    
  222.     Q3View_StartRendering(theDocument->fView );
  223.     do {
  224.         SubmitDocumentData( theDocument ) ;
  225.     } while (Q3View_EndRendering(theDocument->fView) == kQ3ViewStatusRetraverse );
  226.     Q3View_Sync( theDocument->fView ) ;
  227.     return kQ3Success ;
  228. }
  229.  
  230.  
  231. //-------------------------------------------------------------------------------------------
  232. //
  233.  
  234. short HiWrd(long aLong)
  235. {
  236.     return    (((aLong) >> 16) & 0xFFFF) ;
  237. }
  238.  
  239. //-------------------------------------------------------------------------------------------
  240. //
  241.  
  242. short LoWrd(long aLong)
  243. {
  244.     return    ((aLong) & 0xFFFF) ;
  245.  
  246. }
  247.  
  248. //-------------------------------------------------------------------------------------------
  249. //
  250.  
  251. void InitToolbox()
  252. {
  253.     Handle        menuBar = nil;
  254.  
  255.     MaxApplZone() ;
  256.     MoreMasters() ; MoreMasters() ; MoreMasters() ; 
  257.     
  258.     InitGraf( &qd.thePort );
  259.     InitFonts();
  260.     InitWindows();
  261.     InitCursor();
  262.  
  263.     FlushEvents( everyEvent, 0 ) ;
  264.     
  265.     /* initialize application globals */
  266.     gQuitFlag = false;
  267.     
  268. }
  269.  
  270. //-------------------------------------------------------------------------------------------
  271. //
  272.  
  273. void PickAndProcess( 
  274.     WindowPtr     window,
  275.     DocumentPtr    theDocument, 
  276.     Point         mouseLoc )
  277. {
  278.     TQ3WindowPointPickData    myWindowPointPickData;
  279.     TQ3GeometryObject        objectPicked;
  280.     TQ3PickObject            pickObject = NULL ;
  281.     unsigned long            numPicked;
  282.     unsigned long            i;
  283.     TQ3AttributeSet         attribSet;
  284.  
  285.     /* set up the picking data field */
  286.     myWindowPointPickData.data.sort = kQ3PickSortNearToFar;
  287.     myWindowPointPickData.data.mask = kQ3PickDetailMaskObject;
  288.     myWindowPointPickData.data.numHitsToReturn = kQ3ReturnAllHits;
  289.  
  290.     /* get the point of the click in local (window) co-ordinates */
  291.     GlobalToLocal( &mouseLoc ) ;
  292.     myWindowPointPickData.point.x = mouseLoc.h ;
  293.     myWindowPointPickData.point.y = mouseLoc.v  ;
  294.  
  295.     myWindowPointPickData.vertexTolerance = 3.0 ;
  296.     myWindowPointPickData.edgeTolerance      = 3.0 ;
  297.  
  298.     if ((pickObject = Q3WindowPointPick_New( &myWindowPointPickData ))  != NULL) {
  299.  
  300.         Q3View_StartPicking(theDocument->fView, pickObject);
  301.         do {
  302.             SubmitDocumentData(theDocument) ;
  303.         } while (Q3View_EndPicking(theDocument->fView) == kQ3ViewStatusRetraverse );
  304.     }
  305.  
  306.     if (Q3Pick_GetNumHits(pickObject, &numPicked) == kQ3Success) {
  307.  
  308.         /* Get all geometries hit */
  309.         for (i = 0; i < numPicked; i++) {
  310.             if (Q3Pick_GetPickDetailData(
  311.                     pickObject, 
  312.                     i, 
  313.                     kQ3PickDetailMaskObject, 
  314.                     &objectPicked) == kQ3Failure) {
  315.                 break;
  316.             }
  317.  
  318.             /* switch on/off highlighting for this object */
  319.             Q3Geometry_GetAttributeSet(objectPicked, &attribSet);
  320.  
  321.             if (!attribSet) {
  322.                 attribSet = Q3AttributeSet_New();
  323.                 Q3Geometry_SetAttributeSet(objectPicked, attribSet);
  324.             }
  325.  
  326.             /* Set or get the name of the geometry hit */
  327.             ChangeObjectName(objectPicked, attribSet);
  328.  
  329.             Q3Object_Dispose(attribSet);
  330.             Q3Object_Dispose(objectPicked);
  331.         }
  332.  
  333.         DocumentDraw3DData( theDocument ) ;
  334.     }
  335.  
  336.     Q3Object_Dispose(pickObject);     
  337. }
  338.  
  339.  
  340. //-------------------------------------------------------------------------------------------
  341. //
  342.  
  343. void ChangeObjectName(
  344.     TQ3GeometryObject    objectPicked,
  345.     TQ3AttributeSet        attribSet)
  346. {
  347.     DialogPtr    theDialog ;
  348.     Handle        itemHndl = nil;
  349.     Rect        itemRect ;
  350.     short        itemType ;
  351.     short        itemHit ;
  352.     TQ3Switch    highlightSwitch ;
  353.     char        nameString[255] ;
  354.  
  355.     if ( NameAttribute_GetName( objectPicked, nameString) == kQ3Success &&
  356.          *nameString != '\0') {
  357.  
  358.         c2pstr(nameString);
  359.         ParamText((unsigned char *)nameString, (unsigned char *)"\0",  (unsigned char *)"\0",  (unsigned char *)"\0" ) ;
  360.         Alert( 128, nil ) ;
  361.  
  362.         /* add the hightlight attribute it's off now */
  363.         highlightSwitch = kQ3Off ;
  364.         Q3AttributeSet_Add(attribSet, 
  365.                            kQ3AttributeTypeHighlightState,
  366.                            &highlightSwitch);
  367.     }
  368.     else {
  369.         /* add the hightlight attribute it is on now*/
  370.         highlightSwitch = kQ3On ;
  371.         Q3AttributeSet_Add(attribSet, 
  372.                            kQ3AttributeTypeHighlightState,
  373.                            &highlightSwitch);
  374.  
  375.         theDialog = GetNewDialog(128, nil, (WindowPtr)-1) ;
  376.         do {
  377.             ModalDialog(nil, &itemHit);
  378.         } while( itemHit != 1 ) ;
  379.  
  380.         GetDialogItem(theDialog, 4, &itemType, (Handle*)&itemHndl, &itemRect);
  381.         GetDialogItemText(itemHndl, (StringPtr) nameString);
  382.         DisposeDialog( theDialog ) ;
  383.  
  384.         if( itemHndl != nil && objectPicked != nil )
  385.         {
  386.             p2cstr((StringPtr) nameString) ;
  387.             NameAttribute_SetName( objectPicked, (char *)nameString) ;
  388.         }
  389.                    
  390.         DisposeHandle( (Handle)itemHndl ) ;
  391.     }
  392. }
  393.  
  394.  
  395. //-------------------------------------------------------------------------------------------
  396. //
  397. void MainEventLoop()
  398. {
  399.     EventRecord     event;
  400.     WindowPtr       window;
  401.     short           thePart;
  402.     Rect            screenRect, updateRect;
  403.     Point            aPoint = {100, 100};
  404.     CGrafPtr        savedPort ;
  405.     
  406.  
  407.     while( !gQuitFlag )
  408.     {
  409.         if (WaitNextEvent( everyEvent, &event, 10, nil ))
  410.         {
  411.  
  412.             switch (event.what) {
  413.                 case mouseDown:
  414.  
  415.                     thePart = FindWindow( event.where, &window );
  416.  
  417.                     switch( thePart ) {
  418.                         case inMenuBar: 
  419.                             break;
  420.  
  421.                         case inDrag:
  422.  
  423.                             screenRect = (**GetGrayRgn()).rgnBBox;
  424.                             DragWindow( window, event.where, &screenRect );
  425.                             break ;
  426.  
  427.                         case inContent:
  428.  
  429.                             if (window != FrontWindow())
  430.                                 SelectWindow( window );
  431.                             else
  432.                                 PickAndProcess( window, &gDocument, event.where ) ;
  433.                             break ;
  434.  
  435.                         case inGoAway:
  436.                             if (TrackGoAway( window, event.where )) {
  437.                                 DisposeWindow ( window );
  438.                                 gQuitFlag = true;
  439.  
  440.                             }
  441.                             break ;
  442.                             
  443.                         default:
  444.                             break ;
  445.                     }
  446.                     break ;
  447.                             
  448.                         
  449.                 case updateEvt:
  450.                 
  451.                     window = (WindowPtr)event.message;
  452.                     updateRect = (**(window->visRgn)).rgnBBox;
  453.                     SetPort( window ) ;
  454.                     BeginUpdate( window );
  455.                     DocumentDraw3DData( &gDocument ) ;
  456.                     EndUpdate( window );
  457.                     break ;
  458.                     
  459.                 case keyDown:
  460.                 case autoKey:
  461.                     HandleKeyPress(&event);
  462.                     break;
  463.                     
  464.                 case diskEvt:
  465.                     if ( HiWrd(event.message) != noErr ) 
  466.                         (void) DIBadMount(aPoint, event.message);
  467.                     break;
  468.                     
  469.                 case osEvt:
  470.                 case activateEvt:
  471.                     break;
  472.  
  473.  
  474.             }
  475.         }
  476.         else {
  477.             // we received a null event, rotate the cube
  478.             TQ3Matrix4x4    tmp;
  479.             Rect            theRect = ((GrafPtr)gMainWindow)->portRect ;
  480.             
  481.             SetPort((GrafPtr)gMainWindow) ;
  482.             Q3Matrix4x4_SetRotate_XYZ(&tmp, 0.1, 0.12, 0.08);
  483.             Q3Matrix4x4_Multiply(&gDocument.fRotation, &tmp, &gDocument.fRotation);
  484.  
  485.             InvalRect( &theRect ) ;
  486.         }
  487.     }
  488. }
  489.  
  490.  
  491. //-------------------------------------------------------------------------------------------
  492. //
  493. void HandleKeyPress(
  494.     EventRecord *event)
  495. {}
  496.  
  497. //-------------------------------------------------------------------------------------------
  498. //
  499.  
  500. TQ3ViewObject MyNewView(
  501.     WindowPtr theWindow)
  502. {
  503.     TQ3Status                myStatus;
  504.     TQ3ViewObject            myView;
  505.     TQ3DrawContextObject        myDrawContext;
  506.     TQ3RendererObject        myRenderer;
  507.     TQ3CameraObject            myCamera;
  508.     TQ3GroupObject            myLights;
  509.     
  510.     myView = Q3View_New();
  511.     
  512.     //    Create and set draw context.
  513.     if ((myDrawContext = MyNewDrawContext(theWindow)) == nil )
  514.         goto bail;
  515.  
  516.     if ((myStatus = Q3View_SetDrawContext(myView, myDrawContext)) == kQ3Failure )
  517.         goto bail;
  518.  
  519.     Q3Object_Dispose( myDrawContext ) ;
  520.     
  521.     //    Create and set renderer.
  522.     
  523.     
  524.     
  525.     // this would use the wireframe renderer
  526. #if 0
  527.  
  528.     myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeWireFrame);
  529.     if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) {
  530.         goto bail;
  531.     }
  532.     
  533. #else
  534.  
  535.     // this would use the interactive software renderer
  536.  
  537.     if ((myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeInteractive)) != nil ) {
  538.         if ((myStatus = Q3View_SetRenderer(myView, myRenderer)) == kQ3Failure ) {
  539.             goto bail;
  540.         }
  541.         // these two lines set us up to use the best possible renderer,
  542.         // including  hardware if it is installed.
  543.         Q3InteractiveRenderer_SetDoubleBufferBypass (myRenderer, kQ3True);
  544.         Q3InteractiveRenderer_SetPreferences(myRenderer, kQAVendor_BestChoice, 0);
  545.  
  546.     }
  547.     else {
  548.         goto bail;
  549.     }
  550. #endif
  551.  
  552.     Q3Object_Dispose( myRenderer ) ;
  553.     
  554.     //    Create and set camera.
  555.     if ( (myCamera = MyNewCamera(theWindow)) == nil )
  556.         goto bail;
  557.  
  558.     if ((myStatus = Q3View_SetCamera(myView, myCamera)) == kQ3Failure )
  559.         goto bail;
  560.  
  561.     Q3Object_Dispose( myCamera ) ;
  562.     
  563.     //    Create and set lights.
  564.     if ((myLights = MyNewLights()) == nil )
  565.         goto bail;
  566.  
  567.     if ((myStatus = Q3View_SetLightGroup(myView, myLights)) == kQ3Failure )
  568.         goto bail;
  569.  
  570.     Q3Object_Dispose(myLights);
  571.  
  572.     //    Done!!!
  573.     return ( myView );
  574.     
  575. bail:
  576.     //    If any of the above failed, then don't return a view.
  577.     return ( nil );
  578. }
  579.  
  580. //----------------------------------------------------------------------------------
  581.  
  582. TQ3DrawContextObject MyNewDrawContext(
  583.     WindowPtr theWindow )
  584. {
  585.     TQ3DrawContextData        myDrawContextData;
  586.     TQ3MacDrawContextData    myMacDrawContextData;
  587.     TQ3ColorARGB            ClearColor;
  588.     TQ3DrawContextObject    myDrawContext ;
  589.     
  590.     //    Set the background color.
  591.     ClearColor.a = 1.0;
  592.     ClearColor.r = 1.0;
  593.     ClearColor.g = 1.0;
  594.     ClearColor.b = 1.0;
  595.     
  596.     //    Fill in draw context data.
  597.     myDrawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  598.     myDrawContextData.clearImageColor = ClearColor;
  599.     myDrawContextData.paneState = kQ3False;
  600.     myDrawContextData.maskState = kQ3False;
  601.     myDrawContextData.doubleBufferState = kQ3True;
  602.  
  603.     myMacDrawContextData.drawContextData = myDrawContextData;
  604.     
  605.     myMacDrawContextData.window = (CGrafPtr) theWindow;        // this is the window associated with the view
  606.     myMacDrawContextData.library = kQ3Mac2DLibraryNone;
  607.     myMacDrawContextData.viewPort = nil;
  608.     myMacDrawContextData.grafPort = nil;
  609.     
  610.     //    Create draw context and return it, if it’s nil the caller must handle
  611.     myDrawContext = Q3MacDrawContext_New(&myMacDrawContextData) ;
  612.  
  613.     return myDrawContext ;
  614. }
  615.  
  616. //----------------------------------------------------------------------------------
  617.  
  618. TQ3CameraObject MyNewCamera(
  619.     WindowPtr theWindow)
  620. {
  621.     TQ3ViewAngleAspectCameraData    perspectiveData;
  622.     TQ3CameraObject                camera;
  623.     
  624.     TQ3Point3D                     from     = { 0.0, 0.0, 7.25 };
  625.     TQ3Point3D                     to         = { 0.0, 0.0, 0.0 };
  626.     TQ3Vector3D                 up         = { 0.0, 1.0, 0.0 };
  627.  
  628.     float                         fieldOfView = 1.0;
  629.     float                         hither         = 0.1;
  630.     float                         yon         = 10;
  631.     
  632.     TQ3Status                    returnVal = kQ3Failure ;
  633.  
  634.  
  635.     perspectiveData.cameraData.placement.cameraLocation     = from;
  636.     perspectiveData.cameraData.placement.pointOfInterest     = to;
  637.     perspectiveData.cameraData.placement.upVector             = up;
  638.  
  639.     perspectiveData.cameraData.range.hither    = hither;
  640.     perspectiveData.cameraData.range.yon     = yon;
  641.  
  642.     perspectiveData.cameraData.viewPort.origin.x = -1.0;
  643.     perspectiveData.cameraData.viewPort.origin.y = 1.0;
  644.     perspectiveData.cameraData.viewPort.width = 2.0;
  645.     perspectiveData.cameraData.viewPort.height = 2.0;
  646.     
  647.     perspectiveData.fov                = fieldOfView;
  648.     perspectiveData.aspectRatioXToY    =
  649.         (float) (theWindow->portRect.right - theWindow->portRect.left) / 
  650.         (float) (theWindow->portRect.bottom - theWindow->portRect.top);
  651.  
  652.     camera = Q3ViewAngleAspectCamera_New(&perspectiveData);
  653.  
  654.     return camera ;
  655. }
  656.  
  657.  
  658. //----------------------------------------------------------------------------------
  659.  
  660. TQ3GroupObject MyNewLights(
  661.     void )
  662. {
  663.     TQ3GroupPosition        myGroupPosition;
  664.     TQ3GroupObject            myLightList;
  665.     TQ3LightData            myLightData;
  666.     TQ3PointLightData        myPointLightData;
  667.     TQ3DirectionalLightData    myDirectionalLightData;
  668.     TQ3LightObject            myAmbientLight, myPointLight, myFillLight;
  669.     TQ3Point3D                pointLocation = { -10.0, 0.0, 10.0 };
  670.     TQ3Vector3D                fillDirection = { 10.0, 0.0, 10.0 };
  671.     TQ3ColorRGB                WhiteLight = { 1.0, 1.0, 1.0 };
  672.     
  673.     //    Set up light data for ambient light.  This light data will be used for point and fill
  674.     //    light also.
  675.  
  676.     myLightData.isOn = kQ3True;
  677.     myLightData.color = WhiteLight;
  678.     
  679.     //    Create ambient light.
  680.     myLightData.brightness = .2;
  681.     myAmbientLight = Q3AmbientLight_New(&myLightData);
  682.     if ( myAmbientLight == nil )
  683.         goto bail;
  684.     
  685.     //    Create point light.
  686.     myLightData.brightness = 1.0;
  687.     myPointLightData.lightData = myLightData;
  688.     myPointLightData.castsShadows = kQ3False;
  689.     myPointLightData.attenuation = kQ3AttenuationTypeNone;
  690.     myPointLightData.location = pointLocation;
  691.     myPointLight = Q3PointLight_New(&myPointLightData);
  692.     if ( myPointLight == nil )
  693.         goto bail;
  694.  
  695.     //    Create fill light.
  696.     myLightData.brightness = .2;
  697.     myDirectionalLightData.lightData = myLightData;
  698.     myDirectionalLightData.castsShadows = kQ3False;
  699.     myDirectionalLightData.direction = fillDirection;
  700.     myFillLight = Q3DirectionalLight_New(&myDirectionalLightData);
  701.     if ( myFillLight == nil )
  702.         goto bail;
  703.  
  704.     //    Create light group and add each of the lights into the group.
  705.     myLightList = Q3LightGroup_New();
  706.     if ( myLightList == nil )
  707.         goto bail;
  708.     myGroupPosition = Q3Group_AddObject(myLightList, myAmbientLight);
  709.     if ( myGroupPosition == 0 )
  710.         goto bail;
  711.     myGroupPosition = Q3Group_AddObject(myLightList, myPointLight);
  712.     if ( myGroupPosition == 0 )
  713.         goto bail;
  714.     myGroupPosition = Q3Group_AddObject(myLightList, myFillLight);
  715.     if ( myGroupPosition == 0 )
  716.         goto bail;
  717.  
  718.     Q3Object_Dispose( myAmbientLight ) ;
  719.     Q3Object_Dispose( myPointLight ) ;
  720.     Q3Object_Dispose( myFillLight ) ;
  721.  
  722.     //    Done!
  723.     return ( myLightList );
  724.     
  725. bail:
  726.     //    If any of the above failed, then return nothing!
  727.     return ( nil );
  728. }
  729.  
  730.  
  731.  
  732.  
  733. void MyColorBoxFaces( 
  734.     TQ3BoxData *myBoxData )
  735. {
  736.     TQ3ColorRGB                faceColor ;
  737.     short                     face ;
  738.     
  739.     // sanity check - you need to have set up 
  740.     // the face attribute set for the box data 
  741.     // before calling this.
  742.     
  743.     if( myBoxData->faceAttributeSet == NULL )
  744.         return ;
  745.  
  746.     // make each face of a box a different color
  747.     
  748.     for( face = 0; face < 6; face++) {
  749.  
  750.         myBoxData->faceAttributeSet[face] = Q3AttributeSet_New();
  751.         switch( face ) {
  752.             case 0:
  753.                 faceColor.r = 1.0;
  754.                 faceColor.g = 0.0;
  755.                 faceColor.b = 0.0;
  756.                 break;
  757.  
  758.             case 1:
  759.                 faceColor.r = 0.0;
  760.                 faceColor.g = 1.0;
  761.                 faceColor.b = 0.0;
  762.                 break;
  763.  
  764.             case 2:
  765.                 faceColor.r = 0.0;
  766.                 faceColor.g = 0.0;
  767.                 faceColor.b = 1.0;
  768.                 break;
  769.  
  770.             case 3:
  771.                 faceColor.r = 1.0;
  772.                 faceColor.g = 1.0;
  773.                 faceColor.b = 0.0;
  774.                 break;
  775.  
  776.             case 4:
  777.                 faceColor.r = 1.0;
  778.                 faceColor.g = 0.0;
  779.                 faceColor.b = 1.0;
  780.                 break;
  781.  
  782.             case 5:
  783.                 faceColor.r = 0.0;
  784.                 faceColor.g = 1.0;
  785.                 faceColor.b = 1.0;
  786.                 break;
  787.         }
  788.         Q3AttributeSet_Add(myBoxData->faceAttributeSet[face], kQ3AttributeTypeDiffuseColor, &faceColor);
  789.     }
  790. }
  791.  
  792. TQ3GroupPosition MyAddTransformedObjectToGroup( 
  793.     TQ3GroupObject theGroup, 
  794.     TQ3Object theObject, 
  795.     TQ3Vector3D *translation )
  796. {
  797.     TQ3TransformObject    transform;
  798.  
  799.     transform = Q3TranslateTransform_New(translation);
  800.     Q3Group_AddObject(theGroup, transform);    
  801.     Q3Object_Dispose(transform);
  802.     return Q3Group_AddObject(theGroup, theObject);    
  803. }
  804.  
  805.  
  806. TQ3GroupObject MyNewModel(
  807.     void )
  808. {
  809.     TQ3GroupObject            myGroup = NULL;
  810.     TQ3GroupPosition        myGroupPosition;
  811.     TQ3ShaderObject            myIlluminationShader ;
  812.     TQ3BoxData                boxData;
  813.     TQ3ConeData                coneData;
  814.     TQ3CylinderData            cylinderData;
  815.     TQ3TorusData            torusData;
  816.     TQ3GeometryObject        boxGeo,
  817.                             coneGeo,
  818.                             cylinderGeo,
  819.                             torusGeo;
  820.     short                    face ;
  821.     TQ3SetObject            boxFaces[6] ;
  822.     TQ3ColorRGB                color;
  823.     TQ3Vector3D                translation;
  824.  
  825.     // Create a group for the complete model.
  826.     // do not use Q3OrderedDisplayGroup_New since in this
  827.     // type of group all of the translations are applied before
  828.     // the objects in the group are drawn, in this instance we 
  829.     // dont want this.
  830.     if ((myGroup = Q3DisplayGroup_New()) != NULL ) {
  831.  
  832.         // Define a shading type for the group
  833.         // and add the shader to the group
  834.         myIlluminationShader = Q3PhongIllumination_New();
  835.         if (myIlluminationShader != NULL ) {
  836.             Q3Group_AddObject(myGroup, myIlluminationShader);
  837.             Q3Object_Dispose(myIlluminationShader);    
  838.         }
  839.     
  840.  
  841.         // create the box
  842.         // set up the colored faces for the box data
  843.         boxData.faceAttributeSet = boxFaces;
  844.         boxData.boxAttributeSet = nil;
  845.         MyColorBoxFaces( &boxData ) ;
  846.  
  847.         Q3Point3D_Set(&boxData.origin, 0, 0, 0);
  848.         Q3Vector3D_Set(&boxData.orientation, 0, 1.25, 0);
  849.         Q3Vector3D_Set(&boxData.majorAxis, 0, 0, 2);    
  850.         Q3Vector3D_Set(&boxData.minorAxis, 1.25, 0, 0);    
  851.         boxGeo = Q3Box_New(&boxData);
  852.  
  853.  
  854.         // create the cone
  855.         Q3Point3D_Set(&coneData.origin, 0, 0, 0);
  856.         Q3Vector3D_Set(&coneData.orientation, 0, 1.75, 0);
  857.         Q3Vector3D_Set(&coneData.majorRadius, 0, 0, 0.75);    
  858.         Q3Vector3D_Set(&coneData.minorRadius, 0.75, 0, 0);
  859.         coneData.uMin = 0.0;
  860.         coneData.uMax = 1.0;
  861.         coneData.vMin = 0.0;
  862.         coneData.vMax = 1.0;
  863.         coneData.caps = kQ3EndCapMaskBottom;
  864.         coneData.interiorAttributeSet     = NULL;
  865.         coneData.faceAttributeSet         = NULL;
  866.         coneData.bottomAttributeSet        = NULL;
  867.  
  868.         coneData.coneAttributeSet = Q3AttributeSet_New();
  869.         if (coneData.coneAttributeSet != NULL ) {
  870.             Q3ColorRGB_Set(&color, 0.3, 0.9, 0.9);
  871.             Q3AttributeSet_Add(coneData.coneAttributeSet, kQ3AttributeTypeDiffuseColor, &color);
  872.         }
  873.  
  874.         coneGeo = Q3Cone_New(&coneData);
  875.  
  876.  
  877.         // create the cylinder
  878.         Q3Point3D_Set(&cylinderData.origin, 0, 0, 0);
  879.         Q3Vector3D_Set(&cylinderData.orientation, 0, 1.25, 0);
  880.         Q3Vector3D_Set(&cylinderData.majorRadius, 0, 0, 0.75);    
  881.         Q3Vector3D_Set(&cylinderData.minorRadius, 0.75, 0, 0);
  882.         cylinderData.uMin = 0.0;
  883.         cylinderData.uMax = 1.0;
  884.         cylinderData.vMin = 0.0;
  885.         cylinderData.vMax = 1.0;
  886.         cylinderData.caps = kQ3EndCapMaskTop | kQ3EndCapMaskBottom;
  887.         cylinderData.interiorAttributeSet     = NULL;
  888.         cylinderData.topAttributeSet         = NULL;
  889.         cylinderData.faceAttributeSet         = NULL;
  890.         cylinderData.bottomAttributeSet        = NULL;
  891.  
  892.         cylinderData.cylinderAttributeSet = Q3AttributeSet_New();
  893.         if (cylinderData.cylinderAttributeSet != NULL ) {
  894.             Q3ColorRGB_Set(&color, 0.9, 0.3, 0.9);
  895.             Q3AttributeSet_Add(cylinderData.cylinderAttributeSet, kQ3AttributeTypeDiffuseColor, &color);
  896.         }
  897.  
  898.         cylinderGeo = Q3Cylinder_New(&cylinderData);
  899.  
  900.  
  901.         // create the torus
  902.         Q3Point3D_Set(&torusData.origin, 0, 0.8, 0);
  903.         Q3Vector3D_Set(&torusData.orientation, 0, 0.4, 0);
  904.         Q3Vector3D_Set(&torusData.majorRadius, 0, 0, 0.75);    
  905.         Q3Vector3D_Set(&torusData.minorRadius, 0.75, 0, 0);
  906.         torusData.ratio = 1.0;
  907.         torusData.uMin = 0.0;
  908.         torusData.uMax = 1.0;
  909.         torusData.vMin = 0.0;
  910.         torusData.vMax = 1.0;
  911.         torusData.caps = kQ3EndCapNone;
  912.         torusData.interiorAttributeSet     = NULL;
  913.  
  914.         torusData.torusAttributeSet = Q3AttributeSet_New();
  915.         if (torusData.torusAttributeSet != NULL ) {
  916.             Q3ColorRGB_Set(&color, 1.0, 1.0, 0.0);
  917.             Q3AttributeSet_Add(torusData.torusAttributeSet, kQ3AttributeTypeDiffuseColor, &color);
  918.         }
  919.  
  920.         torusGeo = Q3Torus_New(&torusData);
  921.  
  922.  
  923.         // add all geometries to group and translate them
  924.         Q3Vector3D_Set(&translation, 0, 0, 0);
  925.         MyAddTransformedObjectToGroup( myGroup, boxGeo, &translation ) ;
  926.         Q3Object_Dispose( boxGeo );
  927.         for( face = 0; face < 6; face++) {
  928.             if( boxData.faceAttributeSet[face] != NULL )
  929.                 Q3Object_Dispose(boxData.faceAttributeSet[face]);
  930.         }
  931.  
  932.         Q3Vector3D_Set(&translation, 2, 0, 0);
  933.         MyAddTransformedObjectToGroup( myGroup, coneGeo, &translation ) ;
  934.         Q3Object_Dispose(coneGeo);
  935.         if (coneData.coneAttributeSet != NULL )
  936.             Q3Object_Dispose(coneData.coneAttributeSet);
  937.  
  938.         Q3Vector3D_Set(&translation, 0, 0, -2);
  939.         MyAddTransformedObjectToGroup( myGroup, cylinderGeo, &translation ) ;
  940.         Q3Object_Dispose(cylinderGeo);
  941.         if (cylinderData.cylinderAttributeSet != NULL )
  942.             Q3Object_Dispose(cylinderData.cylinderAttributeSet);
  943.  
  944.         Q3Vector3D_Set(&translation, -2, 0, 0);
  945.         MyAddTransformedObjectToGroup( myGroup, torusGeo, &translation ) ;
  946.         Q3Object_Dispose(torusGeo);
  947.         if (torusData.torusAttributeSet != NULL )
  948.             Q3Object_Dispose(torusData.torusAttributeSet);
  949.     }
  950.  
  951.     return ( myGroup );
  952. }
  953.  
  954.